import 'package:dio/dio.dart';
import 'package:flutter_ok/global.dart';
import 'package:flutter_ok/manager/account_manager.dart';
import 'package:flutter_ok/net/base_resp.dart';
import 'package:get/get.dart';

class Api {
  Dio _dio;
  CancelToken _cancelToken;

  static final Api _shared = Api._internal();

  factory Api() => _shared;

  Api._internal() {
    if (_dio == null) {
      BaseOptions options = BaseOptions(
        baseUrl: Global.getBaseUrl(),
        contentType: Headers.jsonContentType,
        responseType: ResponseType.json,
        receiveDataWhenStatusError: false,
        connectTimeout: 20000,
        receiveTimeout: 5000,
        headers: {},
      );

      _dio = Dio(options);

      _cancelToken = new CancelToken();
      //添加拦截器
      _dio.interceptors.add(
        InterceptorsWrapper(
          onRequest: (RequestOptions options) {},
        ),
      );
    }
  }

  /// 请求
  /// method：请求方法
  /// path：请求地址
  /// params：请求参数
  /// success：请求成功回调
  /// error：请求失败回调
  Future _baseRequest<T>(String method, String path,
      {Map params, Function(T) success, Function(Error) error}) async {
    try {
      var response = await _dio.request(path,
          queryParameters: params,
          options: Options(method: method).merge(headers: _getCustomHeader()));
      if (response == null) {
        error(Error(code: -1, message: "未知错误"));
        return;
      }
      BaseResp baseResp = BaseResp<T>.fromJson(response.data);
      //token错误,重新登录
      if (baseResp.isTokenError()) {
        var context = response.extra["context"];
        //跳转登录
        return;
      }
      if (!baseResp.isSuccess()) {
        error(Error(code: baseResp.code, message: baseResp.msg));
        return;
      }
      success(baseResp.data);
    } on DioError catch (e) {
      error(_createError(e));
    } catch (e) {
      error(Error(code: -1, message: e.toString()));
    }
  }

  ///Get请求
  get<T>(String path,
      {Map params, Function(T) success, Function(Error) error}) {
    _baseRequest("get", path, params: params, success: success, error: error);
  }

  ///Post请求
  post<T>(String path,
      {Map params, Function(T) success, Function(Error) error}) {
    _baseRequest("post", path, params: params, success: success, error: error);
  }

  ///Put请求
  put<T>(String path,
      {Map params, Function(T) success, Function(Error) error}) {
    _baseRequest("put", path, params: params, success: success, error: error);
  }

  ///Delete请求
  delete<T>(String path,
      {Map params, Function(T) success, Function(Error) error}) {
    _baseRequest("delete", path,
        params: params, success: success, error: error);
  }

  /// 错误信息
  Error _createError(DioError error) {
    switch (error.type) {
      case DioErrorType.CANCEL:
        {
          return Error(code: -1, message: "请求取消");
        }
        break;
      case DioErrorType.CONNECT_TIMEOUT:
        {
          return Error(code: -1, message: "连接超时");
        }
        break;
      case DioErrorType.SEND_TIMEOUT:
        {
          return Error(code: -1, message: "请求超时");
        }
        break;
      case DioErrorType.RECEIVE_TIMEOUT:
        {
          return Error(code: -1, message: "响应超时");
        }
        break;
      case DioErrorType.RESPONSE:
        {
          try {
            int errCode = error.response.statusCode;
            String errMsg = error.response.statusMessage;
            return Error(code: errCode, message: errMsg);
          } on Exception catch (_) {
            return Error(code: -1, message: "未知错误");
          }
        }
        break;
      default:
        {
          return Error(code: -1, message: error.message);
        }
    }
  }

  /// 获取自定义Header
  Map<String, dynamic> _getCustomHeader() {
    return {
      'Authorization': '${AccountManager.instance.getToken()}',
      'devicePlatform': '${getDevicePlatform()}',
      'version': '${Global.packageInfo.version}',
    };
  }

  static String getDevicePlatform() {
    if (GetPlatform.isDesktop) return "Desktop";
    if (GetPlatform.isWeb) return "Web";
    if (GetPlatform.isFuchsia) return "Fuchsia";
    if (GetPlatform.isAndroid) return "Android";
    if (GetPlatform.isIOS) return "iOS";
    return "";
  }
}

class Error {
  int code;
  String message;

  Error({this.code, this.message});
}
